/*
Copyright (c) 2020-2022, Huawei Technologies Co., Ltd
 All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other materials provided with the distribution.

3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

* Description: 2D图表可视化插件数据显示类
*/
#ifndef ST_SPACE_DISPLAY_H
#define ST_SPACE_DISPLAY_H

#include <cstdint>

#include <qwt_plot_grid.h>
#include <qwt_plot_curve.h>
#include <qwt_legend.h>
#include <qwt_symbol.h>

#include <rviz/properties/enum_property.h>
#include <rviz/properties/int_property.h>
#include <rviz/properties/color_property.h>
#include <rviz/properties/float_property.h>

#include "st_space/st_space_data.h"
#include "st_space/ui_st_widget.h"
#include "common/chart_display_base.h"


namespace chart_plugin {
class StSpaceDisplay : public ChartDisplayBase<custom::StSpace> {
    Q_OBJECT

public:
    StSpaceDisplay() = default;
    ~StSpaceDisplay() override = default;

    /*
     * 功能：自定义插件的初始化函数，在Rviz对插件进行初始化时调用，继承自父类
     * 输入参数：无
     * 输出参数：无
     * 返回值：无
     */
    void onInitialize() override;

    /*
     * 功能：加载配置文件，继承自父类并重写
     * 输入参数：Config
     * 输出参数：无
     * 返回值：无
     */
    virtual void load(const rviz::Config &config);

public Q_SLOTS:
    /*
     * 功能：QWT图例点击的槽，当点击曲线图例时，此槽会被调用以控制曲线是否显示
     * 输入参数：itemInfo-图例对应的QwtPlotCurve ，isVisible-是否可见
     * 输出参数：无
     * 返回值：无
     */
    void LegendChecked(const QVariant &itemInfo, bool isVisible);

    /*
     * 功能：QwtPlot的标题控制槽，当标题控制属性内容被修改时，此槽会被调用以控制界面标题同步修改
     * 输入参数：无
     * 输出参数：无
     * 返回值：无
     */
    void UpdateChartTitle();

    /*
     * 功能：ST图的T轴控制槽，当T轴控制属性内容被修改时，此槽会被调用以控制界面T轴名字同步变化
     * 输入参数：无
     * 输出参数：无
     * 返回值：无
     */
    void UpdateXAxisTitle();

    /*
     * 功能：ST图的S轴控制槽，当S轴控制属性内容被修改时，此槽会被调用以控制界面S轴名字同步变化
     * 输入参数：无
     * 输出参数：无
     * 返回值：无
     */
    void UpdateYAxisTitle();

    /*
     * 功能：更新曲线属性控制选项为用户所选择的曲线
     * 输入参数：无
     * 输出参数：无
     * 返回值：无
     */
    void UpdateCurveChoice();

    /*
     * 功能：更新曲线标题名字为用户更改的名字
     * 输入参数：无
     * 输出参数：无
     * 返回值：无
     */
    void UpdateCurveTitle();

    /*
     * 功能：更新障碍物标题名字为用户更改的名字
     * 输入参数：无
     * 输出参数：无
     * 返回值：无
     */
    void UpdateObjectCurveTitle();

    /*
     * 功能：更新曲线的颜色和透明度为用户修改的值
     * 输入参数：无
     * 输出参数：无
     * 返回值：无
     */
    void UpdateCurveColorAndAlpha();

    /*
     * 功能：更新当前障碍物曲线展示为用户所选择的项
     * 输入参数：无
     * 输出参数：无
     * 返回值：无
     */
    void UpdateObjectsTypeChoice();

    /*
     * 功能：更新障碍物的颜色和透明度为用户所修改的值
     * 输入参数：无
     * 输出参数：无
     * 返回值：无
     */
    void UpdateObjectsTypeColorAndAlpha();

protected:
    /*
     * 功能：清除数据缓存，重新订阅topic，继承自父类
     * 输入参数：无
     * 输出参数：无
     * 返回值：无
     */
    void updateTopic() override;

    /*
     * 功能：StSpaceDisplay插件激活时需要进行的操作，继承自父类
     * 输入参数：无
     * 输出参数：无
     * 返回值：无
     */
    void onEnable() override;

    /*
     * 功能：当接收到topic数据时，由父类回调此接口，继承自父类
     * 输入参数：message-topic接收到的数据指针
     * 输出参数：无
     * 返回值：无
     */
    void ProcessMessage(const custom::StSpace::ConstPtr &message) override;

private:
    /*
     * 功能：初始化标题属性控制元素
     * 输入参数：无
     * 输出参数：无
     * 返回值：无
     */
    void InitTitleProperty();

    /*
     * 功能：初始化第一条曲线属性控制元素
     * 输入参数：curveProperty-EnumProperty
     * 输出参数：无
     * 返回值：无
     */
    void InitFirstCurveProperty(rviz::EnumProperty &curveProperty);

    /*
     * 功能：初始化第二条曲线属性控制元素
     * 输入参数：curveProperty-EnumProperty
     * 输出参数：无
     * 返回值：无
     */
    void InitSecondCurveProperty(rviz::EnumProperty &curveProperty);

    /*
     * 功能：初始化 Speed Limit 曲线属性控制元素
     * 输入参数：curveProperty-EnumProperty
     * 输出参数：无
     * 返回值：无
     */
    void InitSpeedLimitCurveProperty(rviz::EnumProperty &curveProperty);

    /*
     * 功能：初始化插件的曲线属性控制元素
     * 输入参数：无
     * 输出参数：无
     * 返回值：无
     */
    void InitCurveProperty();

    /*
     * 功能：初始化插件的各个属性控制元素
     * 输入参数：无
     * 输出参数：无
     * 返回值：无
     */
    void InitProperty();

    /*
     * 功能：控制当前图例和曲线是否显示
     * 输入参数：item-当前被控制的曲线，isVisible-控制是否显示
     * 输出参数：无
     * 返回值：无
     */
    void ShowCurve(QwtPlotItem *item, bool isVisible);

    /*
     * 功能：清除topic接收到的缓存数据信息
     * 输入参数：无
     * 输出参数：无
     * 返回值：无
     */
    void ClearData();

    /*
     * 功能：清除QwtPlot上的曲线和障碍物显示
     * 输入参数：无
     * 输出参数：无
     * 返回值：无
     */
    void ReplotEmptyData();

    /*
     * 功能：初始化QwtPlot上的元素
     * 输入参数：无
     * 输出参数：无
     * 返回值：无
     */
    void InitQwtPlotStyle();

    /*
     * 功能：初始化曲线显示风格
     * 输入参数：titleProperty-标题属性，colorProperty-颜色属性，alphaProperty-透明度属性
     * 输出参数：curve-曲线
     * 返回值：无
     */
    void InitCurveStyle(QwtPlotCurve &curve, rviz::StringProperty &title,
        const rviz::ColorProperty &color, const rviz::FloatProperty &alpha);

    /*
     * 功能：在QwtPlot上绘制障碍物曲线
     * 输入参数：stObjectsMap-要绘制的障碍物的id信息和数据信息
     * 输出参数：无
     * 返回值：无
     */
    void DrawObjects(const QMap<QString, QPolygonF> &stObjectsMap);

    /*
     * 功能：获取障碍物绘制时需要用到的显示颜色信息
     * 输入参数：type-障碍物的类型信息
     * 输出参数：无
     * 返回值：QColor-颜色信息
     */
    QColor GetObjectsTypeColor(int32_t type);

    /*
     * 功能：设置障碍物绘制时需要用到的显示颜色信息
     * 输入参数：type-障碍物的类型信息，color-颜色信息
     * 输出参数：无
     * 返回值：true-成功，false-失败
     */
    bool SetObjectsTypeColor(int32_t type, const QColor &color);

    /*
     * 功能：设置障碍物绘制时需要用到的显示颜色信息
     * 输入参数：type-障碍物的类型信息，red-红颜色分量信息，green-绿色分量信息，blue-蓝色分量信息
     * 输出参数：无
     * 返回值：void
     */
    void SetObjectsTypeColor(int32_t type, int32_t red, int32_t green, int32_t blue);

    /*
     * 功能：设置障碍物绘制时需要用到的显示颜色透明度信息
     * 输入参数：type-障碍物的类型信息，alpha-透明度值
     * 输出参数：无
     * 返回值：void
     */
    void SetObjectsTypeColorAlpha(int32_t type, int32_t alpha);

    /*
     * 功能：打印配置参数信息
     * 输入参数：config-配置参数对象类
     * 输出参数：无
     * 返回值：无
     */
    void PrintValue(const rviz::Config &config) const;

    /*
     * 功能：创建障碍物控制属性
     * 输入参数：propertyKey-属性元素key名字，propertyValue-属性key元素对应的值
     * 输出参数：无
     * 返回值：无
     */
    void CreateObjectProperty(const QString &propertyKey, const QString &propertyValue);

    /*
     * 功能：创建障碍物类型标题控制属性
     * 输入参数：type-类型，propertyKey-属性元素key名字，propertyValue-属性key元素对应的值
     * 输出参数：无
     * 返回值：无
     */
    void CreateObjectsTypeTitleProperty(int32_t type, const QString &propertyKey, const QString &propertyValue);

    /*
     * 功能：创建障碍物类型颜色控制属性
     * 输入参数：type-类型，propertyKey-属性元素key名字，propertyValue-属性key元素对应的值
     * 输出参数：无
     * 返回值：无
     */
    void CreateObjectsTypeColorProperty(int32_t type, const QString &propertyKey, const QString &propertyValue);

    /*
     * 功能：创建障碍物类型颜色透明度控制属性
     * 输入参数：type-类型，propertyKey-属性元素key名字，propertyValue-属性key元素对应的值
     * 输出参数：无
     * 返回值：无
     */
    void CreateObjectsTypeAlphaProperty(int32_t type, const QString &propertyKey, const QString &propertyValue);

    /*
     * 功能：创建障碍物控制属性
     * 输入参数：type-障碍物的类型
     * 输出参数：无
     * 返回值：无
     */
    void CreateObjectsTypeProperty(int32_t type);

    /*
     * 功能：设置障碍物控制属性
     * 输入参数：objectType-障碍物的类型
     * 输出参数：无
     * 返回值：无
     */
    void SetObjectProperty(int32_t objectType);

    /*
     * 功能：创建并显示障碍物曲线信息
     * 输入参数：stObjectsMap-障碍物的Id和对应的数据
     * 输出参数：无
     * 返回值：无
     */
    void ShowObjects(const QMap<QString, QPolygonF> &stObjectsMap);

    /*
     * 功能：更新当前第一条曲线的属性选项的控制展示
     * 输入参数：无
     * 输出参数：无
     * 返回值：无
     */
    void UpdateFirstCurveChoice();

    /*
     * 功能：更新当前Optimized Curve的属性选项的控制展示
     * 输入参数：无
     * 输出参数：无
     * 返回值：无
     */
    void UpdateOptimizedCurveChoice();

    /*
     * 功能：更新当前StSpeed Curve的属性选项的控制展示
     * 输入参数：无
     * 输出参数：无
     * 返回值：无
     */
    void UpdateStSpeedCurveChoice();

private:
    UiStWidget ui {};
    QWidget widget {};

    QwtPlotGrid grid {};
    QwtPlotCurve firstStTrackCurve {};
    QwtPlotCurve optimizedStTrackCurve {};
    QwtPlotCurve stSpeedLimitCurve {};

    QVector<int32_t> objectsTypeTotalVector {};
    std::map<QString, std::unique_ptr<QwtPlotCurve>> stObjectsCurveMap {};
    StSpaceData stSpaceData {};

    rviz::StringProperty *qwtPlotTitleProperty { nullptr };
    rviz::StringProperty *xAxisTitleProperty { nullptr };
    rviz::StringProperty *yAxisTitleProperty { nullptr };

    rviz::EnumProperty *curveProperty { nullptr };

    rviz::StringProperty *firstCurveTitleProperty { nullptr };
    rviz::ColorProperty *firstCurveColorProperty { nullptr };
    rviz::FloatProperty *firstCurveAlphaProperty { nullptr };

    rviz::StringProperty *optimizedCurveTitleProperty { nullptr };
    rviz::ColorProperty *optimizedCurveColorProperty { nullptr };
    rviz::FloatProperty *optimizedCurveAlphaProperty { nullptr };

    rviz::StringProperty *speedLimitCurveTitleProperty { nullptr };
    rviz::ColorProperty *speedLimitCurveColorProperty { nullptr };
    rviz::FloatProperty *speedLimitCurveAlphaProperty { nullptr };

    rviz::EnumProperty *objectsTypeProperty { nullptr };

    QMap<int32_t, rviz::StringProperty *> objectsTypeTitleProperty {};
    QMap<int32_t, rviz::ColorProperty *> objectsTypeColorProperty {};
    QMap<int32_t, rviz::FloatProperty *> objectsTypeAlphaProperty {};

    QHash<int32_t, QColor> objectsTypeColor {};
};
} // namespace chart_plugin

#endif // ST_SPACE_DISPLAY_H
